package com.example.demo.controller;

import com.example.demo.util.LockUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * ClassName:RedisLockController
 * Package:com.example.demo.controller
 * TODO:
 *
 * @date:2021/10/12 11:07
 * @author:Vicky(陈烟星)
 */
@Slf4j
@RestController
public class RedisLockController {

    private static final String KEY = "LOCK_KEY";


    /**

     * 锁测试共享变量

     */

    private Integer lockCount = 10;



    /**

     * 模拟线程数

     */

    private static int threadNum = 10;


    /**

     * 模拟并发测试加锁和不加锁

     * @return

     */
    @PostMapping(value = "/redisson/lock")
    public void lock(){
        // 计数器

        final CountDownLatch countDownLatch = new CountDownLatch(1);

        for (int i = 0; i < threadNum; i ++) {

            MyRunnable myRunnable = new MyRunnable(countDownLatch);

            Thread myThread = new Thread(myRunnable);

            myThread.start();

        }

        // 释放所有线程

        countDownLatch.countDown();

    }


    /**

     * 加锁测试

     */

    private void testLockCount() {

        String lockKey = "lock-test";

        try {

            // 加锁，设置超时时间2s

            LockUtil.lock(KEY, TimeUnit.SECONDS, 2);

            lockCount--;

            log.info("lockCount值："+lockCount);

        }catch (Exception e){

            log.error(e.getMessage(),e);

        }finally {

            // 释放锁

            LockUtil.unlock(lockKey);

        }

    }





    public class MyRunnable implements Runnable {

        /**

         * 计数器

         */

        final CountDownLatch countDownLatch;


        public MyRunnable(CountDownLatch countDownLatch) {

            this.countDownLatch = countDownLatch;

        }


        @Override

        public void run() {

            try {

                // 阻塞当前线程，直到计时器的值为0

                countDownLatch.await();

            } catch (InterruptedException e) {

                log.error(e.getMessage(),e);

            }
            // 加锁操作

            testLockCount();

        }

    }

}
